package com.meilai.project.service.personal.mission.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.meilai.project.dto.personal.mission.MissionDTO;
import com.meilai.project.dto.personal.mission.MissionOperatorSearchDTO;
import com.meilai.project.dto.personal.mission.MissionSearchDTO;
import com.meilai.project.entity.personal.mission.Mission;
import com.meilai.project.entity.personal.mission.MissionOperator;
import com.meilai.project.entity.personal.mission.MissionRecord;
import com.meilai.project.exception.CommonException;
import com.meilai.project.mapper.personal.mission.MissionMapper;
import com.meilai.project.mapper.personal.mission.MissionOperatorMapper;
import com.meilai.project.mapper.personal.mission.MissionRecordMapper;
import com.meilai.project.service.personal.mission.MissionOperatorService;
import com.meilai.project.service.personal.mission.MissionService;
import com.meilai.project.util.ThreadLocalUserUtil;
import com.meilai.project.vo.personal.mission.MissionOperatorVO;
import com.meilai.project.vo.personal.mission.MissionVO;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 张驰
 * @since 2022-03-24
 */
@Service
public class MissionServiceImpl extends ServiceImpl<MissionMapper, Mission> implements MissionService {

    @Autowired
    private MissionOperatorService missionOperatorService;

    @Autowired
    private MissionRecordMapper missionRecordMapper;

    @Autowired
    private MissionOperatorMapper missionOperatorMapper;

    @Override
    public Page<MissionVO> selectPageList(Integer current_page, Integer page_size, MissionSearchDTO dto) {
        Page<MissionVO> page = new Page<MissionVO>(current_page, page_size);
        List<MissionVO> list = baseMapper.selectPageList(page, dto);
        return page.setRecords(list);
    }

    @Override
    public Page<MissionVO> selectMyMissionList(Integer current_page, Integer page_size, MissionSearchDTO dto) {
        Page<MissionVO> page = new Page<MissionVO>(current_page, page_size);
        Long userId = ThreadLocalUserUtil.get().getId();
        List<MissionVO> list = baseMapper.selectMyMissionList(page, dto, userId);
        return page.setRecords(list);
    }

    @Override
    public Page<MissionOperatorVO> selectTodoMissionList(Integer current_page, Integer page_size, MissionOperatorSearchDTO dto) {
        Page<MissionOperatorVO> page = new Page<>(current_page, page_size);
        Long userId = ThreadLocalUserUtil.get().getId();
        List<MissionOperatorVO> list = missionOperatorMapper.getTodoMissionList(page, userId, dto);
        return page.setRecords(list);
    }

    @Override
    @Transactional
    public boolean addOne(MissionDTO dto) {
        Long userId = ThreadLocalUserUtil.get().getId();
        dto.setCreator_id(userId);
        Mission temp = new Mission();
        BeanUtils.copyProperties(dto, temp);
        setGaps(dto, temp);
        temp.setCur_status(1);
        temp.setComplete_at(null);
        temp.setOff_at(null);
        save(temp);
        updateSalve(temp.getId(), dto.getOperator_ids());
        if (temp.getUse_tip() != null && temp.getUse_tip() == 1) {
            insertTipRecords(temp, false);
        }
        return true;
    }

    @Override
    @Transactional
    public boolean editOne(MissionDTO dto) {
        Mission _temp = getById(dto.getId());
        if (_temp == null) throw new CommonException("当前任务不存在");

        Mission temp = new Mission();
        BeanUtils.copyProperties(dto, temp);
        setGaps(dto, temp);
        temp.setCur_status(1);
        temp.setComplete_at(null);
        temp.setOff_at(null);
        updateById(temp);
        updateSalve(temp.getId(), dto.getOperator_ids());
        if (temp.getUse_tip() != null && temp.getUse_tip() == 1) {
            insertTipRecords(temp, true);
        }
        return true;
    }

    private void setGaps(MissionDTO dto, Mission temp) {
        if (dto.getUse_tip() == 1) {
            Long prev_tip_gap = 0L;
            if (dto.getPrev_tip_gap_unit() == 1) prev_tip_gap = dto.getPrev_tip_gap_num();
            if (dto.getPrev_tip_gap_unit() == 2) prev_tip_gap = dto.getPrev_tip_gap_num() * 60;
            if (dto.getPrev_tip_gap_unit() == 3) prev_tip_gap = dto.getPrev_tip_gap_num() * 60 * 24;
            temp.setPrev_tip_gap(prev_tip_gap);
        }

        if (dto.getUse_continue_tip() == 1) {
            Long continue_tip_gap = 0L;
            if (dto.getContinue_tip_gap_unit() == 1) continue_tip_gap = dto.getContinue_tip_gap_num();
            if (dto.getContinue_tip_gap_unit() == 2) continue_tip_gap = dto.getContinue_tip_gap_num() * 60;
            if (dto.getContinue_tip_gap_unit() == 3) continue_tip_gap = dto.getContinue_tip_gap_num() * 60 * 24;
            temp.setContinue_tip_gap(continue_tip_gap);
        }
    }

    private void insertTipRecords(Mission temp, Boolean edit) {
        if (edit) {
            missionRecordMapper.deleteBeforeRecords(temp.getId());
        }
        try {
            DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            Calendar calendar = Calendar.getInstance();
            Date deadLine = sdf.parse(dtf.format(temp.getDeadline()));
            calendar.setTime(deadLine);
            calendar.add(Calendar.MINUTE, -1 * Integer.parseInt(temp.getPrev_tip_gap().toString()));
            String tip_time = sdf.format(calendar.getTime()); // 任务提醒时间
            if (temp.getUse_continue_tip() == 1) { // 开启持续提醒
                for (int i = 0; i < (temp.getPrev_tip_gap() / temp.getContinue_tip_gap()); i++) {
                    MissionRecord record = new MissionRecord();
                    record.setMission_id(temp.getId());
                    record.setTip_time(LocalDateTime.parse(tip_time, dtf));
                    record.setTime(i);
                    missionRecordMapper.insert(record);
                    //更新下次提醒时间
                    calendar.add(Calendar.MINUTE, Integer.parseInt(temp.getContinue_tip_gap().toString()));
                    tip_time = sdf.format(calendar.getTime());
                }
            } else { // 未开启持续提醒 只提醒一次
                MissionRecord record = new MissionRecord();
                record.setMission_id(temp.getId());
                record.setTip_time(LocalDateTime.parse(tip_time, dtf));
                record.setTime(0);
                missionRecordMapper.insert(record);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }
    }

    private void updateSalve(Long mission_id, List<Long> operator_ids) {
        missionOperatorService.remove(new QueryWrapper<MissionOperator>().eq("mission_id", mission_id));
        List<MissionOperator> mos = new ArrayList<>();
        for (Long operator_id : operator_ids) {
            MissionOperator mo = new MissionOperator();
            mo.setMission_id(mission_id);
            mo.setOperator_id(operator_id);
            mos.add(mo);
        }
        if (CollectionUtils.isNotEmpty(mos)) missionOperatorService.saveBatch(mos);
    }

    @Override
    @Transactional
    public boolean del(List<Long> ids) {
        update(new UpdateWrapper<Mission>().set("deleted_at", LocalDateTime.now()).in("id", ids));
        delConnectData(0, ids);
        return true;
    }

    @Override
    @Transactional
    public boolean off(List<Long> ids) {
        update(new UpdateWrapper<Mission>().set("off_at", LocalDateTime.now()).set("cur_status", 0).in("id", ids));
        delConnectData(0, ids);
        return true;
    }

    @Override
    @Transactional
    public boolean complete(List<Long> ids) {
        update(new UpdateWrapper<Mission>().set("complete_at", LocalDateTime.now()).set("cur_status", 2).in("id", ids));
        delConnectData(1, ids);
        return true;
    }

    @Override
    public boolean operatorComplete(List<Long> ids, String complete_memo) {
        missionOperatorMapper.updateCompleteMemo(ids, complete_memo, LocalDateTime.now());
        // todo 校验是否都完成修改mission表状态
        return true;
    }

    /**
     *
     * @param complete 是否完成任务 1 完成 0 未完成
     */
    private void delConnectData(Integer complete, List<Long> mission_id){
        missionOperatorMapper.updateMissionOperator(LocalDateTime.now(), complete, mission_id);
        missionRecordMapper.deleteBeforeRecordsByIds(mission_id);
    }
}
